package org.jsets.shiro.filter;

import org.apache.shiro.web.filter.mgt.FilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * @description: 重写PathMatchingFilterChainResolver的getChain方法，以便增加HttpMethod支持
 * @author: zyc
 * @date: 2018/11/26 11:43
 **/
public class RestPathMatchingFilterChainResolver extends PathMatchingFilterChainResolver {
    private static transient final Logger log = LoggerFactory.getLogger(RestPathMatchingFilterChainResolver.class);
    public RestPathMatchingFilterChainResolver(PathMatchingFilterChainResolver pathMatchingFilterChainResolver) {
        this.setFilterChainManager(pathMatchingFilterChainResolver.getFilterChainManager());
        this.setPathMatcher(pathMatchingFilterChainResolver.getPathMatcher());
    }

    @Override
    public FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain) {
        FilterChainManager filterChainManager = getFilterChainManager();
        if (!filterChainManager.hasChains()) {
            return null;
        }

        String requestURI = getPathWithinApplication(request);
        String[] strings = null;
        boolean flag = true;

        //the 'chain names' in this implementation are actually path patterns defined by the user.  We just use them
        //as the chain name for the FilterChainManager's requirements
        for (String pathPattern : filterChainManager.getChainNames()) {

            strings = pathPattern.split("==");
            if (strings.length == 2) {
                //url+httpMethod
                // 分割出url+httpMethod,判断httpMethod和request请求的method是否一致,不一致直接false
                if (WebUtils.toHttp(request).getMethod().toUpperCase().equals(strings[1].toUpperCase())) {
                    //一致
                    // If the path does match, then pass on to the subclass implementation for specific checks:
                    if (pathMatches(strings[0], requestURI)) {
                        if (log.isTraceEnabled()) {
                            log.trace("Matched path pattern [" + pathPattern + "] for requestURI [" + requestURI + "].  " +
                                    "Utilizing corresponding filter chain...");
                        }
                        return filterChainManager.proxy(originalChain, pathPattern);
                    }
                } else {
                    //不一致直接跳过
                    continue;
                }
            } else {
                //正常url
                // If the path does match, then pass on to the subclass implementation for specific checks:
                if (pathMatches(pathPattern, requestURI)) {
                    if (log.isTraceEnabled()) {
                        log.trace("Matched path pattern [" + pathPattern + "] for requestURI [" + requestURI + "].  " +
                                "Utilizing corresponding filter chain...");
                    }
                    return filterChainManager.proxy(originalChain, pathPattern);
                }
            }


        }

        return null;
    }
}
